#ifdef KITSCHY_DEBUG_MEMORY 
#include "debug_memorymanager.h"
#endif

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math.h"

#include "BList.h"
#include "BVector.h"
#include "quaternion.h"
#include "symbol.h"
#include "sort.h"
#include "ontology.h"
#include "featureterm.h"
#include "FTKBase.h"
#include "SpecialTerm.h"
#include "ST_floatinterval.h"

#include "AWLocalViewport.h"

#include "AWEntity.h"
#include "AWMessage.h"
#include "AWScenario.h"
#include "AWBody.h"
#include "AWSensor.h"
#include "AWBrain.h"
#include "AWAgent.h"
#include "AWWorld.h"

#include "loader.h"

int agent_names=1;

AW_Agent::AW_Agent() : AW_Entity() {
	class_name->set("AW_Agent");
	Body=0;
	Sensor=0;
	Brain=0;
	AgentName=0;

	O=new Ontology();
	ST_floatInterval::createSort(O);
	Memory=new FTKBase(O);
} /* AW_Agent::AW_Agent */ 


AW_Agent::AW_Agent(Ontology *o,FTKBase *m,AW_Body *bdy,AW_Sensor *sens,AW_Brain *brn) : AW_Entity() {
	class_name->set("AW_Agent");
	Body=bdy;
	Sensor=sens;
	Brain=brn;

	char tmp[80];
	sprintf(tmp,"Agent-%i",agent_names++);
	AgentName=new Symbol(tmp);

	O=o;
	Memory=m;
} /* AW_Agent::AW_Agent */ 


AW_Agent::~AW_Agent() {
	delete AgentName;
	delete Body;
	delete Sensor;
	delete Brain;
	delete Memory;
	delete O;
} /* AW_Agent::~AW_Agent */ 


AW_Agent::AW_Agent(FILE *fp) : AW_Entity()
{
	class_name->set("AW_Agent");
	Body=0;
	Sensor=0;
	Brain=0;
	AgentName=0;

	O=0;
	Memory=0;
	
	load(fp);
} /* AW_Agent */ 


bool AW_Agent::load(FILE *fp)
{
	if (!AW_Entity::load(fp)) return false;

	if (Memory!=0) delete Memory;
	if (O!=0) delete O;

	O=new Ontology(fp);
	ST_floatInterval::createSort(O);
	Memory=new FTKBase(fp,O);

	AgentName=new Symbol(fp);
	Body=(AW_Body *)ClassLoader(fp,O,Memory);
	Sensor=(AW_Sensor *)ClassLoader(fp,O,Memory);
	Brain=(AW_Brain *)ClassLoader(fp,O,Memory);

	return true;
} /* AW_Agent::load */ 


bool AW_Agent::save(FILE *fp)
{
	if (!AW_Entity::save(fp)) return false;

	if (!O->save(fp)) return false;
	if (!Memory->save(fp,0)) return false;

	AgentName->save(fp);
	if (!Body->save(fp)) return false;
	if (!Sensor->save(fp)) return false;
	if (!Brain->save(fp)) return false;

	return true;
} /* AW_Agent::save */ 


void AW_Agent::draw()
{
	Body->draw();
} /* AW_Body::draw */ 


void AW_Agent::localdraw()
{
	Body->localdraw();
} /* AW_Body::localdraw */ 


void AW_Agent::draw_shadows(float lightpos[4])
{
	Body->draw_shadows(lightpos);
} /* AW_Body::draw */ 


void AW_Agent::actualize(float time,float timeinc,AW_World *w)
{
	/* Actualizar agente: */ 
	List<FeatureTerm> l,*posibles;
	FeatureTerm *op;
	List<AW_Message> *msg_queue;
	List<FeatureTerm> *sensor_data;

	posibles=Body->ObtainOps();
	msg_queue=Sensor->ObtainMsg();
	Body->actualize(time,timeinc,msg_queue);
	sensor_data=Sensor->sense(this,w);
	Brain->actualize(time,timeinc,msg_queue,AgentName,sensor_data,posibles,&l);
	delete sensor_data;

	l.Rewind();
	while(l.Iterate(op)) {
		if (Body->ValidOperator(op)) Body->ApplyOperator(op,timeinc,this,w);
	} /* while */ 
	
	delete posibles;
	delete msg_queue;

	Sensor->clear_msg();
} /* AW_Agent::actualize */ 


bool AW_Agent::is_a(char *c)
{
	if (strcmp(c,"AW_Agent")==0) return true;

	return AW_Entity::is_a(c);
} /* AW_Agent::is_a */ 


bool AW_Agent::is_a(Symbol *c)
{
	if (c->cmp("AW_Agent")) return true;

	return AW_Entity::is_a(c);
} /* AW_Agent::is_a */ 


bool AW_Agent::MouseClick(int x,int y)
{
	return Body->MouseClick(x,y);;
} /* AW_Agent::MouseClick */ 


bool AW_Agent::KeyboardEvent(int key)
{
	return Body->KeyboardEvent(key);
} /* AW_Agent::KeyboardEvent */ 



void AW_Agent::pause(void)
{
	Body->pause();
	Sensor->pause();
	Brain->pause();
} /* AW_Agent::pause */ 


void AW_Agent::unpause(void)
{
	Body->unpause();
	Sensor->unpause();
	Brain->unpause();
} /* AW_Agent::unpause */ 


void AW_Agent::receive_msg(AW_Message *m) 
{
//	write_debug_report("AW_Agent [%s]: message received from %s\n",m->receiver->get(),m->sender->get());
	Sensor->receive_msg(m);
} /* AW_Agent::receive_msg */ 

